#include<iostream>
using namespace std;
#include"block_queue.hpp"
#include<time.h>
#include"Task.hpp"

// int myadd(int x,int y){
//     return x+y;
// }




void makeseek(){
    srand((unsigned int)time(nullptr)^getpid());
}

//c:计算，s：保存
template<class C,class S>
class BlockQueues{
public:
    block_queue<C>* c_bq;//这个计算任务的阻塞队列
    block_queue<S>* s_bq;//这个是保存任务的阻塞队列
};


//生产者
void* start_provider(void* args){
    block_queue<CalTask>* bq = (static_cast<BlockQueues<CalTask,SaveTask>*>(args))->c_bq;
    int count = 0;
    while(true){
        //生产活动
        int data1 = rand()%10+1;
        int data2 = rand()%5;
        int operCode = rand()%oper.size();//随机选择运算符的下标
        CalTask t(data1,data2,oper[operCode],mymath);//由于使用了仿函数，所以Task创建的对象可以直接当函数使用

        bq->push(t);
        cout<<"生产者已经生产数据："<<t.toTaskString()<<endl;
        sleep(1);
       //count++;
    }
    delete bq;
    return nullptr;
}


//消费者:除了负责处理计算机任务，还要往阻塞队列里面写入要存放到文件的数据
void* start_consumer(void* args){
    block_queue<CalTask>* bq = (static_cast<BlockQueues<CalTask,SaveTask>*>(args))->c_bq;
    block_queue<SaveTask>* save_bq = (static_cast<BlockQueues<CalTask,SaveTask>*>(args))->s_bq;

    while(true){
        //消费活动
        CalTask t;
        bq->pop(&t);
        string result = t();
        cout<<"消费者消费的数据:"<<result<<endl;

        SaveTask save(result,Save);
        save_bq->push(save);
        cout<<"推送保存任务成功"<<endl;

        //sleep(1);

    }
    delete bq;
    delete save_bq;
    return nullptr;
}



//保存者
void* start_save(void* args){
    block_queue<SaveTask>* save_bq = (static_cast<BlockQueues<CalTask,SaveTask>*>(args))->s_bq;
    while(true){
        SaveTask t;
        save_bq->pop(&t);
        t();
        cout<<"保存任务完成。。。"<<endl;
    }
    delete save_bq;
    return nullptr;
}






int main(){
    makeseek();
    //创建3个新线程来充当消费者和生产者
    //现在需要2个阻塞队列
    BlockQueues<CalTask,SaveTask> bqs;

    bqs.c_bq = new block_queue<CalTask>();
    bqs.s_bq = new block_queue<SaveTask>();




    pthread_t c[2],p[3],s;
    //第4个参数都是这个阻塞队列，因为他们要看到同一块共享资源
    pthread_create(&p[0],nullptr,start_provider,&bqs);
    pthread_create(&p[1],nullptr,start_consumer,&bqs);
    pthread_create(&p[2],nullptr,start_save,&bqs);
    pthread_create(&c[0],nullptr,start_provider,&bqs);
    pthread_create(&c[1],nullptr,start_consumer,&bqs);
    pthread_create(&s,nullptr,start_save,&bqs);
   



    //等待线程
    pthread_join(c[0],nullptr);
    pthread_join(c[1],nullptr);
    pthread_join(s,nullptr);
    pthread_join(p[0],nullptr);
    pthread_join(p[1],nullptr);
    pthread_join(p[2],nullptr);


    delete bqs.c_bq;
    delete bqs.s_bq;
    
    





    return 0;
}

